package net.hasor.dataql.fx.basic;

import net.hasor.dataql.UdfSourceAssembly;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.*;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import javax.inject.Singleton;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Scanner;

/**
 * 自定义 Http 工具包
 *
 * @author tdx.lq
 * @since 2020/9/30 7:08
 */

@Singleton
public class HttpUdfSource implements UdfSourceAssembly {

    /* 会话超时 */
    private static final int SOCKET_TIMEOUT = 60 * 1000;
    /* 响应超时 */
    private static final int CONNECT_REQ_TIMEOUT = 5 * 60 * 1000;
    /* 连接超时 */
    private static final int CONNECT_TIMEOUT = 15 * 1000;

    private static final RequestConfig requestConfig = RequestConfig
            .custom()
            .setSocketTimeout(SOCKET_TIMEOUT)
            .setConnectionRequestTimeout(CONNECT_REQ_TIMEOUT)
            .setConnectTimeout(CONNECT_TIMEOUT)
            .build();

    /**
     * post表单
     *
     * @param urlString      url地址
     * @param nameValuePairs 表单参数 列如：a=1&b=2
     * @return 请求结果
     * @throws IOException 网络IO异常
     */
    public String postForm(String urlString, String nameValuePairs)
            throws IOException {
        URL url = new URL(urlString);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoOutput(true);
        connection.setRequestMethod("POST");
        connection.setUseCaches(false);
        connection.setRequestProperty("CharSet", "UTF-8"); //设置请求编码
        connection.setRequestProperty("Content-Type",
                "application/x-www-form-urlencoded; charset=UTF-8");

        //把建立的http的连接流返回给PrintWriter
        try (PrintWriter out = new PrintWriter(connection.getOutputStream())) {
            out.print(nameValuePairs);
        }

        StringBuilder response = new StringBuilder();
        try (Scanner in = new Scanner(connection.getInputStream(), "utf-8")) {
            int i = 0;
            while (in.hasNextLine()) {
                if (i > 0) {
                    response.append("\n");
                }
                response.append(in.nextLine());
                i++;
            }
        } catch (IOException e) {
            InputStream err = connection.getErrorStream();
            if (err == null)
                throw e;

            try (Scanner in = new Scanner(err, "utf-8")) {
                int i = 0;
                while (in.hasNextLine()) {
                    if (i > 0) {
                        response.append("\n");
                    }
                    response.append(in.nextLine());
                    i++;
                }
            }
        }

        return response.toString();
    }

    /**
     * post json 数据
     *
     * @param url  post地址
     * @param json json数据
     * @return post结果
     */
    public String postJSON(String url, String json) {
        return postJSON(url, json, "utf-8");
    }

    /**
     * post json 数据（支持编码设置）
     *
     * @param url     post网址
     * @param json    json数据
     * @param charset 编码
     * @return post结果
     */
    public String postJSON(String url, String json, String charset) {
        return HttpPostOrPut(url, "post", json, charset);
    }

    /**
     * put json 数据
     *
     * @param url  put地址
     * @param json json数据
     * @return put结果
     */
    public String putJSON(String url, String json) {
        return putJSON(url, json, "utf-8");
    }

    /**
     * put json数据
     *
     * @param url     put地址
     * @param json    json数据
     * @param charset 编码
     * @return put结果
     */
    public String putJSON(String url, String json, String charset) {
        return HttpPostOrPut(url, "put", json, charset);
    }

    /**
     * get url 资源
     *
     * @param url url地址
     * @return url内容
     */
    public String get(String url) {
        return get(url, "utf-8");
    }

    /**
     * get url 资源
     *
     * @param url     url地址
     * @param charset 编码
     * @return url内容
     */
    public String get(String url, String charset) {
        String result = null;

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet httpGet = new HttpGet(url);
            httpGet.setConfig(requestConfig);
            HttpResponse response = httpClient.execute(httpGet);
            if (response != null) {
                result = EntityUtils.toString(response.getEntity(), charset);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return result;
    }

    /**
     * 发送delete请求
     *
     * @param url url地址
     * @return delete请求结果
     */
    public String delete(String url) {
        return delete(url, "utf-8");
    }

    /**
     * 发送delete请求
     *
     * @param url     url地址
     * @param charset 编码
     * @return delete请求结果
     */
    public String delete(String url, String charset) {
        String result = null;

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpDelete httpDelete = new HttpDelete(url);
            httpDelete.setConfig(requestConfig);
            HttpResponse response = httpClient.execute(httpDelete);
            if (response != null) {
                result = EntityUtils.toString(response.getEntity(), charset);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return result;
    }

    /**
     * post/put json 请求
     *
     * @param url     url地址
     * @param method  post/put
     * @param json    json数据
     * @param charset 编码
     * @return post/put结果
     */
    private String HttpPostOrPut(String url, String method, String json, String charset) {
        ;
        String result = null;

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpEntityEnclosingRequestBase httpRequest;
            if ("put".equalsIgnoreCase(method)) {
                httpRequest = new HttpPut(url);
            } else {
                httpRequest = new HttpPost(url);
            }
            httpRequest.setConfig(requestConfig);
            StringEntity entity = new StringEntity(json, charset);
            entity.setContentEncoding(charset);
            entity.setContentType("application/json");
            httpRequest.setEntity(entity);
            HttpResponse response = httpClient.execute(httpRequest);
            if (response != null) {
                result = EntityUtils.toString(response.getEntity(), charset);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return result;
    }
}
